#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fb.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <asm/ioctls.h>
#include <errno.h>
static int OriginalVT = -1;
struct fb_fix_screeninfo FixedInfo;
struct fb_var_screeninfo OrigVarInfo;
static int FrameBufferFD = -1;
void *FrameBuffer = (void *) -1;
static int ConsoleFD = -1;

#define SIGUSR1 10
int openFBDEV(void) {
    /* open the framebuffer device */
    FrameBufferFD = open("/dev/graphics/fb0", O_RDWR);
    if (FrameBufferFD < 0) {
        fprintf(stderr, "Error opening /dev/graphics/fb0\n");
        return -1;
    }

    /* Get the fixed screen info */
    if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
        fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed\n");
        return -1;
    }
    /* get the variable screen info */
    if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
        fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed\n");
        return -1;
    }

    if (FixedInfo.visual != FB_VISUAL_TRUECOLOR && FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
        fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual);
        return -1;
    }

    fprintf(stdout, "FixedInfo: smem_len = %d\n", FixedInfo.smem_len );

    fprintf(stdout, "xres = %d yres = %d bits_per_pixel = %d\n",
        OrigVarInfo.xres,
        OrigVarInfo.yres,
        OrigVarInfo.bits_per_pixel );
    fprintf(stdout, "xoffset:%d yoffset:%d line_length: %d\n",
       OrigVarInfo.xoffset,
       OrigVarInfo.yoffset,
       FixedInfo.line_length );

    struct fb_var_screeninfo newInfo = OrigVarInfo;
    newInfo.bits_per_pixel = 32;
    newInfo.xres = 1366;
    newInfo.yres = 768;
    newInfo.xres_virtual = 1366;
    newInfo.yres_virtual = 768;
    newInfo.xoffset = 0;
    newInfo.yoffset = 0;
    if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &newInfo)) {
        fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed\n");
        return -1;
    }

/* get the variable screen info */
    if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &newInfo)) {
        fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed\n");
        return -1;
    }
    fprintf(stdout, "xres = %d yres = %d bits_per_pixel = %d\n",
        newInfo.xres,
        newInfo.yres,
        newInfo.bits_per_pixel );

    /*
     * fbdev says the frame buffer is at offset zero, and the mmio region
     * is immediately after.
     */
    /* mmap the framebuffer into our address space */
    FrameBuffer = (void *) mmap(0, /* start */
        FixedInfo.smem_len, /* bytes */
        PROT_READ | PROT_WRITE, /* prot */
        MAP_SHARED, /* flags */
        FrameBufferFD, /* fd */
        0 /* offset */);
     if (FrameBuffer == (void *) - 1) {
        fprintf(stderr, "error: unable to mmap framebuffer\n");
        return -1;
    }
    return 0;
}

int closeFBDEV(void) {
    /* restore original variable screen info*/
    if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
        fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed)\n");
        return -1;
    }
    munmap(FrameBuffer, FixedInfo.smem_len);
    close(FrameBufferFD);
}

int main() {
    openFBDEV();
    fprintf(stderr, "openFBDEV finish\n");
    int i=0;
    uint32_t color = 0xFFFF0000;
    uint32_t* pixels = FrameBuffer;
    for(i=0;i<FixedInfo.smem_len/4;i++)
       pixels[i] = color;

    sleep(10);
    closeFBDEV(); 
    fprintf(stderr, "closeFBDEV finish\n");
    return 0;
}
